"""DaemonSet资源Markdown写入器模块"""

from typing import Dict, Any, List
import yaml
from src.writers.base import Writer
from src.utils.markdown_builder import MarkdownBuilder

class DaemonSetWriter(Writer):
    """
    DaemonSet资源Markdown写入器
    负责将提取的DaemonSet资源信息写入Markdown文件
    """
    
    def write(self, data: Dict[str, Any], output_path: str) -> None:
        """
        将提取的DaemonSet信息写入Markdown
        
        Args:
            data: 提取的DaemonSet信息
            output_path: 输出文件路径
        """
        if not data or data.get("kind") != "DaemonSet":
            self.logger.warning(f"无效的DaemonSet数据: {data.get('name', '未知')}")
            return
        
        # 创建Markdown构建器
        md = self.create_markdown_builder()
        
        # 收集节标题，用于生成目录
        sections = ["基本信息", "节点选择", "更新策略", "容器", "存储卷"]
        
        # 标题
        md.header(f"DaemonSet: {data.get('name', '未知')}", 1)
        
        # 命名空间
        md.bold("命名空间:").text(f" {data.get('namespace', 'default')}").newline(2)
        
        # 目录
        if len(sections) > 3:  # 只有当节较多时才添加目录
            md.toc(sections)
        
        # 基本信息
        self._write_basic_info(md, data)
        
        # 节点选择
        self._write_node_selection(md, data)
        
        # 更新策略
        self._write_update_strategy(md, data)
        
        # 容器信息
        self._write_containers(md, data)
        
        # 卷信息
        self._write_volumes(md, data)
        
        # 生成Markdown文件
        self.write_markdown(md, output_path)
    
    def _write_basic_info(self, md: MarkdownBuilder, data: Dict[str, Any]) -> None:
        """
        写入基本信息
        
        Args:
            md: Markdown构建器
            data: DaemonSet数据
        """
        md.header("基本信息", 2)
        
        # 基本元数据表
        basic_info = {
            "名称": data.get("name", ""),
            "命名空间": data.get("namespace", "default"),
            "创建时间": data.get("creation_timestamp", "")
        }
        
        # 添加状态信息
        status = data.get("status", {})
        if status:
            basic_info["当前Pod数"] = status.get("current_number_scheduled", 0)
            basic_info["期望Pod数"] = status.get("desired_number_scheduled", 0)
            basic_info["就绪Pod数"] = status.get("number_ready", 0)
            basic_info["可用Pod数"] = status.get("number_available", 0)
            
            if "updated_number_scheduled" in status:
                basic_info["已更新Pod数"] = status.get("updated_number_scheduled")
                
            if "number_misscheduled" in status:
                misscheduled = status.get("number_misscheduled", 0)
                if misscheduled > 0:
                    basic_info["错误调度Pod数"] = misscheduled
        
        md.dict_table(basic_info)
        
        # 标签和注解
        if data.get("labels"):
            md.header("标签", 3)
            md.dict_table(data.get("labels", {}))
        
        if data.get("annotations"):
            md.header("注解", 3)
            md.dict_table(data.get("annotations", {}))
    
    def _write_node_selection(self, md: MarkdownBuilder, data: Dict[str, Any]) -> None:
        """
        写入节点选择信息
        
        Args:
            md: Markdown构建器
            data: DaemonSet数据
        """
        md.header("节点选择", 2)
        
        pod_spec = data.get("template", {}).get("spec", {})
        
        # 选择器
        if data.get("selector"):
            md.header("选择器", 3)
            md.dict_table(data.get("selector", {}).get("match_labels", {}))
        
        # 节点选择器
        if pod_spec.get("node_selector"):
            md.header("节点选择器", 3)
            md.dict_table(pod_spec.get("node_selector", {}))
        
        # 节点亲和性
        if pod_spec.get("affinity", {}).get("node_affinity"):
            md.header("节点亲和性", 3)
            node_affinity = pod_spec.get("affinity", {}).get("node_affinity", {})
            
            # 必需的节点亲和性
            if "required_during_scheduling_ignored_during_execution" in node_affinity:
                md.paragraph("**必需的节点亲和性**（调度时必须满足以下条件）：")
                required = node_affinity.get("required_during_scheduling_ignored_during_execution", {})
                self._write_affinity_terms(md, required.get("node_selector_terms", []))
            
            # 首选的节点亲和性
            if "preferred_during_scheduling_ignored_during_execution" in node_affinity:
                md.paragraph("**首选的节点亲和性**（调度时优先考虑以下条件）：")
                preferred = node_affinity.get("preferred_during_scheduling_ignored_during_execution", [])
                for pref in preferred:
                    weight = pref.get("weight", 1)
                    md.paragraph(f"权重: **{weight}**")
                    self._write_affinity_terms(md, [pref.get("preference", {})])
        
        # 容忍度
        if pod_spec.get("tolerations"):
            md.header("容忍度", 3)
            tolerations = pod_spec.get("tolerations", [])
            
            headers = ["键", "值", "效果", "容忍时间"]
            rows = []
            
            for toleration in tolerations:
                key = toleration.get("key", "")
                value = toleration.get("value", "")
                effect = toleration.get("effect", "")
                
                # 翻译effect为更友好的说明
                effect_map = {
                    "NoSchedule": "不调度",
                    "PreferNoSchedule": "尽量不调度",
                    "NoExecute": "不执行"
                }
                effect = effect_map.get(effect, effect)
                
                toleration_seconds = toleration.get("toleration_seconds", "")
                if toleration_seconds:
                    toleration_seconds = f"{toleration_seconds}秒"
                
                rows.append([key, value, effect, toleration_seconds])
            
            md.table(headers, rows)
    
    def _write_affinity_terms(self, md: MarkdownBuilder, terms: List[Dict[str, Any]]) -> None:
        """
        写入亲和性条件
        
        Args:
            md: Markdown构建器
            terms: 亲和性条件列表
        """
        for i, term in enumerate(terms):
            if i > 0:
                md.paragraph("**或**")
                
            if "match_expressions" in term:
                with md.list() as lst:
                    for expr in term.get("match_expressions", []):
                        key = expr.get("key", "")
                        operator = expr.get("operator", "")
                        values = expr.get("values", [])
                        
                        # 翻译operator为更友好的说明
                        operator_map = {
                            "In": "在列表中",
                            "NotIn": "不在列表中",
                            "Exists": "存在",
                            "DoesNotExist": "不存在",
                            "Gt": "大于",
                            "Lt": "小于"
                        }
                        operator = operator_map.get(operator, operator)
                        
                        if values:
                            lst.item(f"{key} {operator} [{', '.join(values)}]")
                        else:
                            lst.item(f"{key} {operator}")
            
            if "match_fields" in term:
                with md.list() as lst:
                    for field in term.get("match_fields", []):
                        key = field.get("key", "")
                        operator = field.get("operator", "")
                        values = field.get("values", [])
                        
                        # 翻译operator为更友好的说明
                        operator_map = {
                            "In": "在列表中",
                            "NotIn": "不在列表中",
                            "Exists": "存在",
                            "DoesNotExist": "不存在"
                        }
                        operator = operator_map.get(operator, operator)
                        
                        if values:
                            lst.item(f"字段 {key} {operator} [{', '.join(values)}]")
                        else:
                            lst.item(f"字段 {key} {operator}")
    
    def _write_update_strategy(self, md: MarkdownBuilder, data: Dict[str, Any]) -> None:
        """
        写入更新策略
        
        Args:
            md: Markdown构建器
            data: DaemonSet数据
        """
        md.header("更新策略", 2)
        
        update_strategy = data.get("update_strategy", {})
        if not update_strategy:
            md.paragraph("未指定更新策略，使用默认配置")
            return
        
        strategy_type = update_strategy.get("type", "")
        
        # 翻译策略类型为更友好的说明
        strategy_map = {
            "RollingUpdate": "滚动更新",
            "OnDelete": "删除时更新"
        }
        strategy_type = strategy_map.get(strategy_type, strategy_type)
        
        md.paragraph(f"更新策略类型: **{strategy_type}**")
        
        # 滚动更新设置
        if "rolling_update" in update_strategy:
            rolling_update = update_strategy.get("rolling_update", {})
            
            if "max_unavailable" in rolling_update:
                max_unavailable = rolling_update.get("max_unavailable", "")
                md.paragraph(f"最大不可用数: **{max_unavailable}**")
            
            if "max_surge" in rolling_update:
                max_surge = rolling_update.get("max_surge", "")
                md.paragraph(f"最大超量: **{max_surge}**")
    
    def _write_containers(self, md: MarkdownBuilder, data: Dict[str, Any]) -> None:
        """
        写入容器信息
        
        Args:
            md: Markdown构建器
            data: DaemonSet数据
        """
        md.header("容器", 2)
        
        # 获取容器信息
        pod_spec = data.get("template", {}).get("spec", {})
        containers = pod_spec.get("containers", [])
        
        if not containers:
            md.paragraph("未定义容器")
            return
        
        # 遍历每个容器
        for i, container in enumerate(containers):
            container_name = container.get("name", f"container-{i+1}")
            md.header(f"容器 {i+1}: {container_name}", 3)
            
            # 基本容器信息
            with md.list() as lst:
                lst.item(f"**镜像:** {container.get('image', '未指定')}")
                
                if "image_pull_policy" in container:
                    lst.item(f"**镜像拉取策略:** {container.get('image_pull_policy')}")
                    
                if "command" in container:
                    command = " ".join(container.get("command", []))
                    lst.item(f"**命令:** `{command}`")
                    
                if "args" in container:
                    args = " ".join(container.get("args", []))
                    lst.item(f"**参数:** `{args}`")
            
            # 端口
            if container.get("ports"):
                md.header("端口", 4)
                
                headers = ["名称", "容器端口", "协议"]
                rows = []
                
                for port in container.get("ports", []):
                    rows.append([
                        port.get("name", ""),
                        str(port.get("container_port", "")),
                        port.get("protocol", "TCP")
                    ])
                
                md.table(headers, rows)
            
            # 环境变量
            if container.get("env"):
                md.header("环境变量", 4)
                
                headers = ["名称", "值", "来源"]
                rows = []
                
                for env in container.get("env", []):
                    name = env.get("name", "")
                    value = env.get("value", "")
                    value_from = ""
                    
                    if "value_from" in env:
                        value_from_dict = env.get("value_from", {})
                        if "configMapKeyRef" in value_from_dict:
                            cm_ref = value_from_dict.get("configMapKeyRef", {})
                            value_from = f"ConfigMap: {cm_ref.get('name', '')}.{cm_ref.get('key', '')}"
                        elif "secretKeyRef" in value_from_dict:
                            secret_ref = value_from_dict.get("secretKeyRef", {})
                            value_from = f"Secret: {secret_ref.get('name', '')}.{secret_ref.get('key', '')}"
                        elif "fieldRef" in value_from_dict:
                            field_ref = value_from_dict.get("fieldRef", {})
                            value_from = f"Field: {field_ref.get('field_path', '')}"
                    
                    rows.append([name, value, value_from])
                
                md.table(headers, rows)
                
            # 资源限制
            if container.get("resources"):
                md.header("资源配置", 4)
                
                resources = container.get("resources", {})
                requests = resources.get("requests", {})
                limits = resources.get("limits", {})
                
                if requests:
                    md.bold("请求:").newline()
                    
                    with md.list() as lst:
                        for resource_type, value in requests.items():
                            lst.item(f"{resource_type}: {value}")
                    
                    md.newline()
                
                if limits:
                    md.bold("限制:").newline()
                    
                    with md.list() as lst:
                        for resource_type, value in limits.items():
                            lst.item(f"{resource_type}: {value}")
                    
                    md.newline()
            
            # 健康检查
            if container.get("liveness_probe"):
                md.header("存活探针", 4)
                self._write_probe(md, container.get("liveness_probe", {}))
            
            if container.get("readiness_probe"):
                md.header("就绪探针", 4)
                self._write_probe(md, container.get("readiness_probe", {}))
            
            # 卷挂载
            if container.get("volume_mounts"):
                md.header("卷挂载", 4)
                
                headers = ["名称", "挂载路径", "只读"]
                rows = []
                
                for mount in container.get("volume_mounts", []):
                    name = mount.get("name", "")
                    path = mount.get("mount_path", "")
                    read_only = "是" if mount.get("read_only", False) else "否"
                    
                    rows.append([name, path, read_only])
                
                md.table(headers, rows)
                
            # 安全上下文
            if container.get("security_context"):
                md.header("安全上下文", 4)
                md.dict_table(container.get("security_context", {}))
    
    def _write_probe(self, md: MarkdownBuilder, probe: Dict[str, Any]) -> None:
        """
        写入探针信息
        
        Args:
            md: Markdown构建器
            probe: 探针信息字典
        """
        with md.list() as lst:
            # 初始延迟
            if "initial_delay_seconds" in probe:
                lst.item(f"初始延迟: {probe.get('initial_delay_seconds')}秒")
            
            # 超时
            if "timeout_seconds" in probe:
                lst.item(f"超时: {probe.get('timeout_seconds')}秒")
            
            # 周期
            if "period_seconds" in probe:
                lst.item(f"周期: {probe.get('period_seconds')}秒")
            
            # 成功阈值
            if "success_threshold" in probe:
                lst.item(f"成功阈值: {probe.get('success_threshold')}")
            
            # 失败阈值
            if "failure_threshold" in probe:
                lst.item(f"失败阈值: {probe.get('failure_threshold')}")
            
            # 探针类型和参数
            if "http_get" in probe:
                http_get = probe.get("http_get", {})
                path = http_get.get("path", "/")
                port = http_get.get("port", 80)
                lst.item(f"HTTP GET 探针: {path} (端口: {port})")
            elif "tcp_socket" in probe:
                tcp_socket = probe.get("tcp_socket", {})
                port = tcp_socket.get("port", 80)
                lst.item(f"TCP Socket 探针: 端口 {port}")
            elif "exec" in probe:
                exec_probe = probe.get("exec", {})
                command = exec_probe.get("command", [])
                if command:
                    cmd_str = " ".join(command)
                    lst.item(f"Exec 探针: `{cmd_str}`")
    
    def _write_volumes(self, md: MarkdownBuilder, data: Dict[str, Any]) -> None:
        """
        写入卷信息
        
        Args:
            md: Markdown构建器
            data: DaemonSet数据
        """
        md.header("存储卷", 2)
        
        # 获取卷信息
        pod_spec = data.get("template", {}).get("spec", {})
        volumes = pod_spec.get("volumes", [])
        
        if not volumes:
            md.paragraph("未定义存储卷")
            return
            
        # 遍历每个卷
        for i, volume in enumerate(volumes):
            volume_name = volume.get("name", f"volume-{i+1}")
            md.header(f"卷 {i+1}: {volume_name}", 3)
            
            # 确定卷类型并格式化
            if "config_map" in volume:
                config_map = volume.get("config_map", {})
                md.bold("类型:").text(" ConfigMap").newline()
                md.bold("ConfigMap名称:").text(f" {config_map.get('name', '')}").newline()
                
                if "items" in config_map:
                    md.newline().bold("配置项:").newline()
                    
                    with md.list() as lst:
                        for item in config_map.get("items", []):
                            key = item.get("key", "")
                            path = item.get("path", "")
                            lst.item(f"{key} -> {path}")
            
            elif "secret" in volume:
                secret = volume.get("secret", {})
                md.bold("类型:").text(" Secret").newline()
                md.bold("Secret名称:").text(f" {secret.get('name', '')}").newline()
                
                if "items" in secret:
                    md.newline().bold("配置项:").newline()
                    
                    with md.list() as lst:
                        for item in secret.get("items", []):
                            key = item.get("key", "")
                            path = item.get("path", "")
                            lst.item(f"{key} -> {path}")
            
            elif "host_path" in volume:
                host_path = volume.get("host_path", {})
                md.bold("类型:").text(" hostPath").newline()
                md.bold("路径:").text(f" {host_path.get('path', '')}").newline()
                
                if "type" in host_path:
                    type_map = {
                        "": "未指定",
                        "DirectoryOrCreate": "目录或创建",
                        "Directory": "目录",
                        "FileOrCreate": "文件或创建",
                        "File": "文件",
                        "Socket": "套接字",
                        "CharDevice": "字符设备",
                        "BlockDevice": "块设备"
                    }
                    type_value = host_path.get("type", "")
                    md.bold("类型:").text(f" {type_map.get(type_value, type_value)}").newline()
            
            elif "empty_dir" in volume:
                empty_dir = volume.get("empty_dir", {})
                md.bold("类型:").text(" emptyDir").newline()
                
                if "medium" in empty_dir:
                    md.bold("存储介质:").text(f" {empty_dir.get('medium', 'Memory')}").newline()
                
                if "size_limit" in empty_dir:
                    md.bold("大小限制:").text(f" {empty_dir.get('size_limit', '')}").newline()
            
            elif "persistent_volume_claim" in volume:
                pvc = volume.get("persistent_volume_claim", {})
                md.bold("类型:").text(" PersistentVolumeClaim").newline()
                md.bold("PVC名称:").text(f" {pvc.get('claim_name', '')}").newline()
                md.bold("只读:").text(f" {'是' if pvc.get('read_only', False) else '否'}").newline()
            
            else:
                # 处理其他可能的卷类型
                volume_type = next(iter(volume.keys()), "unknown")
                if volume_type != "name":
                    md.bold("类型:").text(f" {volume_type}").newline()
                    md.bold("详细信息:").newline()
                    
                    with md.code_block("yaml"):
                        md.text(yaml.dump(volume, default_flow_style=False))